from PyQt5.QtCore import *
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from param.Parameter import Parameter

class HeatingThread(QThread):

    heating_on = pyqtSignal(str, str, str)

    def __init__(self, addrFrontActual, addrMidActual, addrBackActual):
        super(HeatingThread, self).__init__()
        self.working = True
        self.modbusClient = None

        # 设置默认温度数据的起始地址
        self.addrFrontActual = addrFrontActual
        self.addrMidActual = addrMidActual
        self.addrBackActual = addrBackActual
        # 读取寄存器的个数
        self.quantity = 2

        # 采样时间间隔
        self.interval = 100


    def setModbusClient(self, modbusClient):
        self.modbusClient = modbusClient

    def __del__(self):
        self.working = False
        self.wait()

    def quit(self) -> None:
        super(HeatingThread, self).quit()
        self.working = False


    def setReadAddress(self, address, quantity):
        """修改温度数据的地址"""
        self.address = address
        self.quantity = quantity

    def run(self):
        self.working = True
        while self.working:
            try:
                # 转换为小数
                result1 = self.modbusClient.read_holding_registers(self.addrFrontActual, self.quantity, unit=0x01)
                result2 = self.modbusClient.read_holding_registers(self.addrMidActual, self.quantity, unit=0x01)
                result3 = self.modbusClient.read_holding_registers(self.addrBackActual, self.quantity, unit=0x01)
                front = BinaryPayloadDecoder.fromRegisters(result1.registers[0:2], Endian.Big, wordorder=Endian.Big).decode_32bit_float()
                mid = BinaryPayloadDecoder.fromRegisters(result2.registers[0:2], Endian.Big, wordorder=Endian.Big).decode_32bit_float()
                back = BinaryPayloadDecoder.fromRegisters(result3.registers[0:2], Endian.Big, wordorder=Endian.Big).decode_32bit_float()
                # 发送携带数据的信号，浮点数保留三位小数
                self.heating_on.emit("%.1f" % front, "%.1f" % mid, "%.1f" % back)
                # 设置读取的时间间隔，当前是100ms一次
                self.msleep(self.interval)
            except Exception as e:
                print(e)

class SpeedThread(QThread):

    torque_on = pyqtSignal(str)
    def __init__(self, addrSpeedActual):
        super(SpeedThread, self).__init__()
        self.working = True
        self.modbusClient = None

        self.addrSpeedActual = addrSpeedActual
        self.quantity = 2

        self.interval = 100


    def setModbusClient(self, modbusClient):
        self.modbusClient = modbusClient

    def __del__(self):
        self.working = False
        self.wait()

    def setReadAddress(self, address, quantity):
        self.addrSpeedActual = address
        self.quantity = quantity

    def quit(self) -> None:
        super(SpeedThread, self).quit()
        self.working = False

    def run(self):
        self.working = True
        while self.working:
            try:
                result = self.modbusClient.read_holding_registers(self.addrSpeedActual, self.quantity, unit=0x01)
                speed = BinaryPayloadDecoder.fromRegisters(result.registers[0:2], Endian.Big,
                                                           wordorder=Endian.Big).decode_32bit_float()
                self.torque_on.emit("%.1f" % speed)
                self.msleep(self.interval)
            except Exception as e:
                print(e)

class TorqueThread(QThread):
    send_param = pyqtSignal(str, str, int)

    def __init__(self, addrTorque, addrMeltTemper):
        super(TorqueThread, self).__init__()
        self.working = True
        self.modbusClient = None

        self.addrTorque = addrTorque
        self.addrMeltTemper = addrMeltTemper
        self.quantity = 2

        self.interval = 100

    def setModbusClient(self, modbusClient):
        self.modbusClient = modbusClient

    def __del__(self):
        self.working = False
        self.wait()

    def quit(self) -> None:
        super(TorqueThread, self).quit()
        self.working = False

    def setReadAddress(self, address, quantity):
        self.address = address
        self.quantity = quantity

    def run(self):
        self.working = True
        while self.working:
            try:
                result1 = self.modbusClient.read_holding_registers(self.addrTorque, self.quantity, unit=0x01)
                result2 = self.modbusClient.read_holding_registers(self.addrMeltTemper, self.quantity, unit=0x01)
                torque = BinaryPayloadDecoder.fromRegisters(result1.registers[0:2], Endian.Big,
                                                           wordorder=Endian.Big).decode_32bit_float()
                temper = BinaryPayloadDecoder.fromRegisters(result2.registers[0:2], Endian.Big,
                                                            wordorder=Endian.Big).decode_32bit_float()


                self.send_param.emit("%.1f" % torque, "%.1f" % temper, self.interval)
                # self.send_param.emit(str(torque), str(temper), self.interval)
                self.msleep(self.interval)

            except Exception as e:
                print(e)


class ThreadFactory:
    def __init__(self):

        self.parameter = Parameter()
        # 获取地址
        self.addrTemperFrontActual = self.parameter.getTemperFrontActual()
        self.addrTemperMidActual = self.parameter.getTemperMidActual()
        self.addrTemperBackActual = self.parameter.getTemperBackActual()
        self.addrSpeedActual = self.parameter.getSpeedActual()
        self.addrTorque = self.parameter.getTorque()
        self.addrMeltTemper = self.parameter.getMeltTemper()
        # 创建线程，同时注入地址
        self.heatingThread = HeatingThread(self.addrTemperFrontActual, self.addrTemperMidActual, self.addrTemperBackActual)
        self.speedThread = SpeedThread(self.addrSpeedActual)
        self.torqueThread = TorqueThread(self.addrTorque, self.addrMeltTemper)

    def getHeatingThread(self):
        return self.heatingThread

    def getSpeedThread(self):
        return self.speedThread

    def getTorqueThread(self):
        return self.torqueThread
